package ahct.log;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.PrintStream;
import java.nio.ByteBuffer;
import java.nio.channels.FileChannel;
import java.util.Date;

import ahct.log.asynchronous.LogEntity;
import ahct.log.asynchronous.LogQueue;

/**
 * FileOperate
 * @author ChuTao
 * Copyright © lxchutao(楚涛) 2011-2015  lxchutao@163.com  QQ:290363711  http://blog.csdn.net/chutao  http://lxchutao.cnblogs.com
 */
public class FileOperate
{
    /**
     * 日志文件扩展名
     */
    private final String _log_extension = ".log";
    
    /**
     * 日志文件路径+文件名（不含文件扩展名）
     */
    private String _dirAndName = "SimpleLogger";
    
    /**
     * <默认构造函数>
     */
    FileOperate(String dirAndName)
    {
        if (dirAndName != null && !dirAndName.equals(""))
        {
            this._dirAndName = dirAndName;
        }
    }
    
    /**
     * 打开一个文件，向其中追加指定的字符串，然后关闭该文件。 如果文件不存在，此方法创建一个文件，将指定的字符串写入文件，然后关闭该文件。 如果文件大小超过一兆(可配置)，则转储备份并新建一同名文件，再追加，然后关闭该文件。
     * 
     * @param logFileSuffix 日志文件后缀（用以分开记录日志之用，若不分开记录日志可为空）
     * @param contents 要追加到文件中的字符串
     * @param isAsyn isAsyn TRUE异步记入日志，FALSE
     * @see [类、类#方法、类#成员]
     */
    void AppendFile(final String logFileSuffix, final String contents, Boolean isAsyn)
    {
        String filename_full = this._dirAndName + logFileSuffix + this._log_extension;
        
        if (isAsyn)
        {
            LogEntity entity = new LogEntity();
            entity.set_log_contents(contents);
            entity.set_file_dir_name(this._dirAndName);
            entity.set_log_file_suffix(logFileSuffix);
            entity.set_log_extension(this._log_extension);
            // LogQueue.LOG_QUEUE.offer(entity);
            // LogQueue.LOG_QUEUE.poll();
            try
            {
                LogQueue.LOG_QUEUE.put(entity);
                // LogQueue.LOG_QUEUE.take();
            }
            catch (InterruptedException e)
            {
                e.printStackTrace();
            }
        }
        else
        {
            File file = new File(filename_full);
            try
            {
                if (file.exists())
                {
                    if (file.length() > JLogger.getInstance().getLogFileMaxsize())
                    {
                        String path = this._dirAndName + logFileSuffix + "_" + new Date().getTime()
                            + this._log_extension;
                        File destFile = new File(path);
                        // boolean isRenamed = file.renameTo(destFile);
                        // boolean isDeleted = file.createNewFile();
                        // boolean isCreated = file.delete();// file.createNewFile();
                        // System.out.println(isRenamed + " " + isDeleted + "  " + isCreated);
                        copyUseChannel(file, destFile);
                        FileOutputStream out = new FileOutputStream(filename_full, false);
                        out.write(0);
                        // PrintStream p = new PrintStream(out);
                        // p.println("");
                    }
                }
                else
                {
                    if (file.getParentFile() != null && !file.getParentFile().exists())
                    {
                        // String str = file.getAbsolutePath();
                        file.getParentFile().mkdirs();
                    }
                    file.createNewFile();
                }
                
                FileOutputStream out = new FileOutputStream(filename_full, true);
                PrintStream p = new PrintStream(out);
                p.println(contents);
                // out.write(contents.getBytes("utf-8"));
            }
            catch (FileNotFoundException e)
            {
                e.printStackTrace();
            }
            catch (IOException e)
            {
                e.printStackTrace();
            }
        }
    }
    
    /**
     * 使用FileChannel拷贝文件
     * 
     * @param srcFile
     * @param destFile
     * @throws IOException
     * @see [类、类#方法、类#成员]
     */
    public static void copyUseChannel(File srcFile, File destFile)
        throws IOException
    {
        if ((!srcFile.exists()) || (srcFile.isDirectory()))
        {
            return;
        }
        if (!destFile.exists())
        {
            // createFile(destFile.getAbsolutePath());
            destFile.createNewFile();
        }
        FileChannel out = null;
        FileChannel in = null;
        try
        {
            in = new FileInputStream(srcFile).getChannel();
            out = new FileOutputStream(destFile).getChannel();
            
            ByteBuffer buffer = ByteBuffer.allocate(102400);
            int position = 0;
            int length = 0;
            while (true)
            {
                length = in.read(buffer, position);
                if (length <= 0)
                {
                    break;
                }
                // System.out.println("after read:"+buffer);
                buffer.flip();
                // System.out.println("after flip:"+buffer);
                out.write(buffer, position);
                position += length;
                buffer.clear();
                // System.out.println("after clear:"+buffer);
            }
        }
        finally
        {
            if (out != null)
            {
                out.close();
            }
            if (in != null)
            {
                in.close();
            }
        }
    }
    
}
